﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Runtime.Serialization.Json;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using SWFToImage;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace KoalaGIS.Tools.BaiduDoc
{
    [Serializable]
    public class BaiduDocInfo
    {
        /// <summary>
        /// 文件编号
        /// </summary>
        [DataMember(Name="docId")]
        [JsonProperty("docId")]
        public string doc_id;

        /// <summary>
        /// 分类编号
        /// </summary>
        [DataMember(Name = "docTypeNum")]
        [JsonProperty("docTypeNum")]
        public string cid;

        /// <summary>
        /// 价格
        /// </summary>
        public string price;


        public string value_average;

        /// <summary>
        /// 文件大小
        /// </summary>
        [DataMember(Name = "size")]
        [JsonProperty("size")]
        public string doc_size;

        [DataMember(Name = "title")]
        [JsonProperty("title")]
        public string doc_name;

        [DataMember(Name = "docType")]
        [JsonProperty("docType")]
        public string doc_type;

        [DataMember(Name = "totalPageNum")]
        public string totalPageNum;

        public string url;
        public string wealth;
        public string level;
        public string isOrgDoc;
    }

    public delegate void DownLoadingHandler( int total, int curnum );

    /// <summary>
    /// 百度文库下载类
    /// </summary>
    public class BaiduDocDownload
    {
        /// <summary>
        /// 存放下载文件的文件夹
        /// </summary>
        private string _downDir = "D:\\BaiduDown\\";

        private DownLoadingHandler _downloadingHandler = null;

        public event DownLoadingHandler Jpg2PdfEvent;

        public event DownLoadingHandler SwfDownLoadEvent;

        public BaiduDocDownload()
        {
            ///设置程序运行时的目录为当前目录
            this._downDir = AppDomain.CurrentDomain.BaseDirectory;

            this._downDir += "//downloads";
            if (!System.IO.Directory.Exists(this._downDir))
            {
                System.IO.Directory.CreateDirectory(this._downDir);
            }

        }
        /// <summary>
        /// 获取文档资源信息
        /// </summary>
        /// <param name="url">文档地址</param>
        /// <returns></returns>
        public BaiduDocInfo GetDocInfo(string url)
        {
            //url : http://wenku.baidu.com/view/e6698789680203d8ce2f248b.html
            //抓取页面源文件
            System.Net.HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);

            WebResponse response = request.GetResponse();

            Stream smRes = response.GetResponseStream();

            /*
             * //读取byte
            byte[] resBuf = new byte[10240];
            int nReaded = 0;
            MemoryStream memSm = new MemoryStream();
            while ((nReaded = smRes.Read(resBuf, 0, 10240)) != 0)
            {
                memSm.Write(resBuf, 0, nReaded);
            }

            byte[] byResults = memSm.ToArray();

            memSm.Close();
             * */

            //获取string
            StreamReader rd = new StreamReader(smRes, Encoding.Default);
            string str = "";
            //while (rd.Peek() > -1)
            //{
            //    str += rd.ReadLine();
            //}
            str = rd.ReadToEnd();

            string html = str;



            //正则表达式替换源文件，找到
            //BAIDU_DOC_INFO = @"^[/s/S]*DOC_INFO=(/{.*?})[/s/S]*$";

            //BAIDU_DOC_INFO = @"^[/s/S]*WkInfo.DocInfo=(/{.*?})[/s/S]*$";

            /*
            Regex reg = new Regex(@"?<=WkInfo.DocInfo=.*WkInfo.PaceInfo");

            Match match = reg.Match(html);
            if (match.Success)
            {
                string json = match.Value;
            }
             * */

            string result = GetValue(html, "WkInfo.DocInfo = ", "'readerVersion'");
            result = result.Trim();
            //int pos = result.LastIndexOf(',');
            result = result.TrimEnd(',');
            result += "}";

            result = result.Replace("//贡献者", "").Replace("//文档标题", "").Replace("//文档格式号", "").Replace("//文档格式", "").Replace("//文档分类", "").Replace("//文档价格", "").Replace("//文档评分", "");

            //result = result.Replace('\'', '\"');

            BaiduDocInfo docInfo = JsonToObject<BaiduDocInfo>(result);

            return docInfo;
            
        }


        public void Process(BaiduDocInfo docInfo, string baseDir )
        {
            
            //System.IO.File.Delete(
            
            string url = "";

            int pagesize = int.Parse( docInfo.totalPageNum );
            string docType = docInfo.doc_type;
            string docid = docInfo.doc_id;

            if (docType.ToLower() == "doc")
            {
                url = "http://ai.wenku.baidu.com/play/" + docid;
            }
            else
            {
                throw new NotImplementedException("doc以外的文档还没实现");
            }

            ////string tempDir = this._downDir + "";
            //if (!System.IO.Directory.Exists(this._downDir + "//temp"))
            //{
            //    System.IO.Directory.CreateDirectory(this._downDir + "//temp");
            //}

            //baseDir = this._downDir + "//temp";

            for (int i = 0; i < pagesize; i++)
            {
                if (this.SwfDownLoadEvent != null)
                {
                    this.SwfDownLoadEvent(pagesize, i);
                }

                string downUrl = url + "?pn=" + (i+1) + "&rn=1";
                WebResponse response = GetGetResponse(downUrl);
                byte[] bytes = getResponseStream(response);

                string path = baseDir + "//" + (i+1) + ".swf";
                FileStream fs = new FileStream(path, FileMode.Create);
                fs.Write(bytes, 106, bytes.Length - 106);
                fs.Close();

                this.swf2jpg(path, baseDir + "//" + (i + 1) + ".jpg");

                
            
            }

            return;

            int countPerPage = 10;
            int nCount = pagesize / countPerPage;

            for (int i = 0; i < nCount; i++)
            {
                int start = i * countPerPage + 1;
                int end = (i + 1) * countPerPage;

                string downUrl = url + "?pn=" + start + "&rn=" + countPerPage;

                WebResponse response = GetGetResponse(downUrl);
                byte[] bytes = getResponseStream(response);

                string path = baseDir + i + ".swf";
                FileStream fs = new FileStream(path, FileMode.Create);
                fs.Write(bytes, 106, bytes.Length - 106);
                fs.Close();
            }

            int leftCount = pagesize % countPerPage;
            if (leftCount > 0)
            {
                int start = nCount * countPerPage + 1;
                string downUrl = url + "?pn=" + start + "&rn=" + leftCount;
            }

            /*
            string url = "http://wenku.baidu.com/play/ac1177333968011ca3009124?pn=1&rn=1";


            Zjgis.Geosoc.Utils.Web.HttpRequestHelper helper = new Utils.Web.HttpRequestHelper();
            byte[] bytes = helper.GetGetResponse(url);
            FileStream fs = new FileStream("D:\\output.swf", FileMode.Create);
            fs.Write(bytes, 106, bytes.Length - 106);
            fs.Close();



            SWFToImage.SWFToImageObject si = new SWFToImage.SWFToImageObjectClass();
            si.InitLibrary("name", "sn");
            si.InputSWFFileName = "D:\\output.swf";
            si.ImageHeight = 1256;
            si.ImageWidth = 1256;
            si.ImageOutputType = SWFToImage.TImageOutputType.iotGIF;
            si.FrameIndex = 1;
            si.Execute();
            si.SaveToFile("D:\\swf.jpg");
             * */
        }

        public void swf2jpg(string swffilepath, string outfile )
        {
            SWFToImageObject si = new SWFToImageObjectClass();
            si.InitLibrary("KoalaGIS", "KoalaGIS");
            si.InputSWFFileName = swffilepath;
            
            si.ImageHeight = 1415;
            si.ImageWidth = 1000;
            si.ImageOutputType = SWFToImage.TImageOutputType.iotGIF;
            si.FrameIndex = 1;
            si.Execute();
            si.SaveToFile(outfile);
        }

        public void jpg2pdf(string dir, string outpdfpaath)
        {
            //创建一个Document实例
            Document pdf = new Document(new Rectangle(0,0, 1000,1415));

            //为该Document创建一个Writer实例
            PdfWriter.GetInstance( pdf, new FileStream(outpdfpaath,FileMode.Create) );
            
            //打开当前Document
            pdf.Open();


            //为当前Document添加内容
            //pdf.Add(new Paragraph("Hello World"));

            string[] jpgfiles = System.IO.Directory.GetFiles(dir, "*.jpg", SearchOption.TopDirectoryOnly);
            jpgfiles = jpgfiles.OrderBy(p => p).ToArray();


            for (int i = 0; i < jpgfiles.Length; i++)
            {
                /*
                if (this._downloadingHandler != null)
                {
                    this._downloadingHandler(jpgfiles.Length, i);
                }
                 * */

                if (this.Jpg2PdfEvent != null)
                {
                    this.Jpg2PdfEvent(jpgfiles.Length, i);
                }
                //string filepath = jpgfiles[i];
                string filepath = dir + "//" + (i + 1 ) + ".jpg";
                Image jpg = Image.GetInstance(filepath);
                //jpg.Alignment = Jpeg.;
                pdf.Add(jpg);
            }

            //关闭Document
            pdf.Close();


        }


        public void DownLoadPdf(string url)
        {

            BaiduDocInfo docInfo = this.GetDocInfo(url);

            string baseDIR = this._downDir + "//temp";
            if (!System.IO.Directory.Exists(baseDIR))
            {
                System.IO.Directory.CreateDirectory(baseDIR);
            }

            this.Process(docInfo, baseDIR);

            string docname = docInfo.doc_name;
            if (string.IsNullOrEmpty(docname))
                docname = "百度文档";

            string pdfilepath = this._downDir + "//" + docname + ".pdf";
            this.jpg2pdf(baseDIR, pdfilepath);

            System.IO.Directory.Delete(this._downDir + "//temp",true);
        }

        /// <summary>
        /// 获得字符串中开始和结束字符串中间得值
        /// </summary>
        /// <param name="str">字符串</param>
        /// <param name="s">开始</param>
        /// <param name="e">结束</param>
        /// <returns></returns> 
        public static string GetValue(string str, string s, string e)
        {
            Regex rg = new Regex("(?<=(" + s + "))[.\\s\\S]*?(?=(" + e + "))", RegexOptions.Multiline | RegexOptions.Singleline);
            return rg.Match(str).Value;
        }


        public static T JsonToObject<T>(string json)
        {
            /*
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
            System.IO.MemoryStream ms = new System.IO.MemoryStream(Encoding.UTF8.GetBytes(json));
            T obj = (T)serializer.ReadObject(ms);
            ms.Close();
            return obj;
             * */

            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(json);
        }

        public static WebResponse GetGetResponse(string url)
        {
            System.Net.HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            WebResponse res = request.GetResponse();
            return res;
        }

        public static byte[] getResponseStream(WebResponse response)
        {
            Stream smRes = response.GetResponseStream();

            byte[] resBuf = new byte[10240];
            int nReaded = 0;
            MemoryStream memSm = new MemoryStream();
            while ((nReaded = smRes.Read(resBuf, 0, 10240)) != 0)
            {
                memSm.Write(resBuf, 0, nReaded);
            }

            byte[] byResults = memSm.ToArray();

            memSm.Close();

            return byResults;
        }

        
    }
}
